package variabilitysmelldetection.plugin.views;

import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.UIPlugin;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.ViewPart;

import variabilitysmelldetection.WriteCSV;
import variabilitysmelldetection.analyses.GodMethod;
import variabilitysmelldetection.measurement.Measurement;
import variabilitysmelldetection.measurement.measures.Measure;
import variabilitysmelldetection.measurement.models.MethodItem;
import variabilitysmelldetection.measurement.models.Project;
import variabilitysmelldetection.plugin.Activator;
import de.ovgu.featureide.core.IFeatureProject;


@SuppressWarnings("restriction")
public class GodMethodView extends ViewPart {

	public static final String ID = "variabilitysmelldetection.plugin.views.GodMethodView";

	private TableViewer viewer;
	private Project project;
	private IFeatureProject featureProject;
	private List<MethodItem> items;

	/**
	 * The constructor.
	 */
	public GodMethodView() {}

	/**
	 * Shows the given selection in this view.
	 */
	public void show(IFeatureProject featureProject, Project project, List<MethodItem> items) {
		this.featureProject = featureProject;
		this.project = project;
		this.items = items;

		viewer.setInput(items);
		viewer.refresh(true);
	}

	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(final Composite parent) {

		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);

		final Label strategy = new Label(parent, SWT.CENTER);
		strategy.setText("Strategy: " + (new GodMethod().getStrategy()));

		GridData gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.grabExcessHorizontalSpace = true;
		strategy.setLayoutData(gridData);

		Activator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				strategy.setText("Strategy: " + (new GodMethod().getStrategy()));	    		
			}
		});

		Button saveButton = new Button(parent, SWT.PUSH);
		saveButton.setText("Save as CSV");
		saveButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (items == null || items.isEmpty()) {
					MessageDialog.openInformation(parent.getShell(), "VSD God Method", "Please, select the detection option in the popup menu before saving the detection results.");

				} else {

					if (WriteCSV.writeGodMethods(project, items)){
						MessageDialog.openInformation(parent.getShell(), "VSD God Method", "Methods with code smell saved in '"+WriteCSV.OUTPUT_FOLDER_NAME + WriteCSV.GODMETHODS_FILE_NAME+"'");

					} else {
						MessageDialog.openError(parent.getShell(), "VSD God Method", "Error in saving methods with code smell.");
					}
				}
			}
		}); 

		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);

		viewer.setComparator(new ViewerComparator());

		createColumns(parent, viewer);

		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				IStructuredSelection sel = (IStructuredSelection) event.getSelection();
				MethodItem method = (MethodItem) sel.getFirstElement();
				if(method != null){
//				IPath path = new Path("features/"+method.getParent().getParentName()+"/"+method.getParent().getName());
					IPath path = new Path(method.getParent().getPath());
					IFile file = featureProject.getProject().getFile(path);
					IWorkbenchWindow dw = UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
					IWorkbenchPage page = dw.getActivePage();
					if (page != null) {
						IContentType contentType = null;
						try {
							IContentDescription description = file
									.getContentDescription();
							if (description != null) {
								contentType = description.getContentType();
							}
							IEditorDescriptor desc = null;
							if (contentType != null) {
								desc = PlatformUI.getWorkbench().getEditorRegistry()
										.getDefaultEditor(file.getName(), contentType);
							} else {
								desc = PlatformUI.getWorkbench().getEditorRegistry()
										.getDefaultEditor(file.getName());
							}

							if (desc != null) {
								page.openEditor(new FileEditorInput(file), desc.getId());
							} else {
								// case: there is no default editor for the file
								page.openEditor(new FileEditorInput(file),
										"org.eclipse.ui.DefaultTextEditor");
							}
						} catch (CoreException e) {
							System.out.println(e);
						}
					}
				}
			}
		});
		
		viewer.setContentProvider(new ArrayContentProvider());

		// make the selection available to other views
		getSite().setSelectionProvider(viewer);

		// define layout for the viewer
		gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);

	}

	// create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
		Measure[] measures = Measurement.getMethodMeasures();

		// line number
		TableViewerColumn col = createTableViewerColumn("#", 30);
		col.setLabelProvider(new ColumnLabelProvider() {

			public void update(ViewerCell cell) {
				Table table = viewer.getTable();
				cell.setText(table.indexOf((TableItem)cell.getItem())+1+"");
			} 
		});

		// feature name
		col = createTableViewerColumn("Feature", 180);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				MethodItem m = (MethodItem) element;
				return m.getParent().getParentName();
			}
		});

		// component name
		col = createTableViewerColumn("Component", 180);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				MethodItem m = (MethodItem) element;
				return m.getParent().getName();
			}
		});

		// method name
		col = createTableViewerColumn("Method", 250);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				MethodItem m = (MethodItem) element;
				return m.getName();
			}
		});

		// refinement
		col = createTableViewerColumn("Refinement?", 100);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				MethodItem m = (MethodItem) element;
				return m.isRefinement() ? "Y" : "N";
			}
		});

		for (final Measure m : measures) {

			col = createTableViewerColumn(m.getAcronym(), 70);
			col.setLabelProvider(new ColumnLabelProvider() {
				@Override
				public String getText(Object element) {
					MethodItem method = (MethodItem) element;
					Measure measure = method.getMeasure(m.getClass());
					return Double.toString(measure.getValue());
				}
			});
		}

	}

	private TableViewerColumn createTableViewerColumn(String title, int bound) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
}